#include "mirror.hpp"

#include "qbe/src/ecs/app.hpp"

#include "qbe/src/ecs/query.hpp"

#include "qbe/src/axis/axis.hpp"
#include "qbe/src/input/input.hpp"
#include "qbe/src/select/select.hpp"
#include "qbe/src/state/state.hpp"
#include "qbe/src/undoRedo/undoRedo.hpp"
#include "qbe/src/utils/utils.hpp"

#include "qbe/src/layout/layout.hpp"

#include "qlib/all.h"

namespace qbe::mirror {

// 退出模式时回调
void exit_callback(ecs::Query query, state::AllModeType mode) {
  auto& move_param = query.get_resource<Models>();
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();
  auto& state = query.get_resource<state::State>();

  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;

  move_param.reset();
}

void init(ecs::Commands commands, ecs::Query query) {
  Models models;
  commands.insert_resource(models);

  auto& state = query.get_resource<state::State>();
  state.addExitCall(state::EditingModeType::Mirror, exit_callback);
}

// 退出模式
void exit(ecs::Query query) {
  // 获取移动参数
  auto& move_param = query.get_resource<Models>();
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();

  // 获取reg
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;

  // 退出模式
  auto& state = query.get_resource<state::State>();
  state.exit();

  move_param.reset();
}

// 帧开始，模式转换
void stateTransformBegin(Models& models, state::State& state, input::HandleBundle* handle, ecs::Bus& bus, ecs::Query query, bool isOneObj) {
  if (models.state == State::None) {
    qbe::UiMessage::OpenMirrorUi event;
    event.isX = models.isXMirror;
    event.isOneObj = isOneObj;

    bus.send(event);

    models.state = State::Wait;
  }

  if (models.state == State::Wait) {
    auto ok_event = bus.receive<qbe::UiMessage::MirrorOk>();
    auto cancel_event = bus.receive<qbe::UiMessage::MirrorCancel>();

    if (!ok_event.empty()) {
      models.state = State::Complete;
      models.dis = ok_event.back().dis;
      models.isSelf = ok_event.back().isSelf;
      return;
    }

    if (!cancel_event.empty()) {
      models.state = State::Cancel;
      return;
    }
  }
}

// 帧尾-退出模式
void stateTransformEnd(State& state) {
  // 操作模式执行完就回退
  if (state == State::Cancel) {}
}

// 移动逻辑
void update(ecs::Query query, ecs::Bus& bus) {
  // 判断编辑模式为移动
  auto& state = query.get_resource<state::State>();

  if (state.getEditingMode() != state::EditingModeType::Mirror) {
    return;
  }

  // 获取cell和reg
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();

  bool isOneObj = true;
  int index = 0;

  auto view_one = reg.view<select::SelectTag>();
  view_one.each([&isOneObj, &index](entt::entity e) {
    if (index == -1) {
      isOneObj = false;
    }
    index = -1;
  });

  // 获取输入 坐标系 撤销恢复
  auto& handModule = query.get_resource<vsg::ref_ptr<input::HandleBundle>>();
  auto& axisModule = query.get_resource<axis::Axis>();
  auto& undoRedoModule = query.get_resource<undoRedoT::UndoRedoModule>();

  // 获取移动参数
  auto& models = query.get_resource<Models>();

  stateTransformBegin(models, state, handModule, bus, query, isOneObj);

  if (models.state == State::Cancel) {
    models.reset();
    state.exit();
    return;
  }

  if (models.state == State::Complete) {
    if (models.isSelf) {
      qlib::Vec2dArray box;
      qlib::Vec2d center;
      auto view = reg.view<select::SelectTag>();

      undoRedoModule.start(cell);
      view.each([&reg, &undoRedoModule, &models, &layout_cmd, &box, &center](entt::entity e) {
        if (utils::getBox(reg, e, box)) {
          center = (box[0] + box[1]) / 2.0;

          if (models.isXMirror) {
            center.x += models.dis;
          } else {
            center.y += models.dis;
          }

          const double max_value = 1000000;

          qlib::Vec2d pos1 = center, pos2 = center;
          if (models.isXMirror) {
            pos1.y = -max_value;
            pos2.y = max_value;
          } else {
            pos1.x = -max_value;
            pos2.x = max_value;
          }

          undoRedoModule.change(e);

          utils::mirror(reg, e, pos1, pos2);

          layout_cmd.update(e);
        }
      });
      undoRedoModule.end();
    } else {
      qlib::Vec2dArray box = utils::getInitBox();
      qlib::Vec2dArray box_t;

      auto view = reg.view<select::SelectTag>();
      view.each([&reg, &box, &box_t, &models](entt::entity e) {
        if (utils::getBox(reg, e, box_t)) {
          box = utils::boxAndBox(box, box_t);
        }
      });

      qlib::Vec2d center = (box[0] + box[1]) / 2.0;

      if (models.isXMirror) {
        center.x += models.dis;
      } else {
        center.y += models.dis;
      }

      const double max_value = 1000000;

      qlib::Vec2d pos1 = center, pos2 = center;
      if (models.isXMirror) {
        pos1.y = -max_value;
        pos2.y = max_value;
      } else {
        pos1.x = -max_value;
        pos2.x = max_value;
      }

      undoRedoModule.start(cell);
      view.each([&reg, &undoRedoModule, &pos1, &pos2, &layout_cmd](entt::entity e) {
        undoRedoModule.change(e);

        utils::mirror(reg, e, pos1, pos2);

        layout_cmd.update(e);
      });
      undoRedoModule.end();
    }

    auto& sele_event_writer = query.get_event_writer<select::Event>();
    sele_event_writer.send({select::Code::SelectUpdate});
    sele_event_writer.send({select::Code::HoverUpdate});

    models.reset();
    state.exit();
    return;
  }

  stateTransformEnd(models.state);
}

void Plugin::build(ecs::App& app) {
  app.add_stage<InitStage>();
  app.add_stage<UpdateStage>();

  app.add_systems<InitStage>(init);
  app.add_systems<UpdateStage>(update);
}

}  // namespace qbe::mirror